package m.html.form;

import m.system.util.StringUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FormEvent {
    private FormEvent(String method,String url,String param){
        this.method=EventMethod.AJAX;
        this.methodName=method;
        this.url=url;
        this.param=param;
        this.fillData=new ArrayList<>();
        this.beforeMethod=new ArrayList<>();
        this.successMethod=new ArrayList<>();
        this.afterMethod=new ArrayList<>();
    }
    private EventMethod method;
    protected final String methodName;
    private final String url;
    private final String param;
    private int width=1000;
    private final List<String> fillData;
    private final List<String> beforeMethod;
    private final List<String> successMethod;
    private final List<String> afterMethod;
    private String methodJs;
    private String returnJs;

    /**
     * 加载data
     */
    public static FormEvent loadData(String url,String param){
        return new FormEvent("loadData",url,param);
    }

    /**
     * 请求方法
     */
    public static FormEvent doJson(String method,String url,String param){
        return new FormEvent(method,url,param);
    }

    /**
     * 加载页面 MODAL
     */
    public static FormEvent toModal(String method,String url,String param,int width){
        FormEvent event=new FormEvent(method,url,param);
        event.width=width;
        event.method=EventMethod.MODAL;
        return event;
    }
    /**
     * 加载页面 PAGE
     */
    public static FormEvent toPage(String method,String url,String param){
        FormEvent event=new FormEvent(method,url,param);
        event.method=EventMethod.PAGE;
        return event;
    }
    /**
     * 加载页面 DRAWER
     */
    public static FormEvent toDrawer(String method,String url,String param,int width){
        FormEvent event=new FormEvent(method,url,param);
        event.width=width;
        event.method=EventMethod.DRAWER;
        return event;
    }

    /**
     * 执行成功返回
     */
    public final static FormEvent backTrue=custom("backTrue","this.back(true);");
    /**
     * 执行成功返回(其他方法执行成功后的flag)
     */
    public final static FormEvent backFlag=custom("backFlag","this.back();");
    /**
     * 执行成功返回，并返回model对象
     */
    public final static FormEvent backModel=custom("backModel","this.back(true,this.model);");
    /**
     * 自定义JS事件
     */
    public static FormEvent custom(String method,String js){
        FormEvent event=new FormEvent(method,"","");
        event.method=EventMethod.JS;
        event.methodJs=js;
        return event;
    }

    /**
     * testAndMsg 成对出现，test为表达式，false则提示
     */
    public static FormEvent verify(String method,FormJsTest... formJsTests){
        FormEvent event=new FormEvent(method,"","");
        event.method=EventMethod.JS;
        StringBuilder str= new StringBuilder();
        for(FormJsTest test : formJsTests){
            str.append(test.toJsString());
        }
        event.methodJs= str.toString();
        return event;
    }

    /**
     * 成功后填充data
     */
    public FormEvent fillData(String... field){
        this.fillData.addAll(Arrays.asList(field));
        return this;
    }

    /**
     * 事件开始执行 返回false可阻止事件继续执行
     */
    public FormEvent before(String... methodName){
        this.beforeMethod.addAll(Arrays.asList(methodName));
        return this;
    }

    /**
     * 成功后执行
     */
    public FormEvent success(String... methodName){
        this.successMethod.addAll(Arrays.asList(methodName));
        return this;
    }
    /**
     * 事件后执行
     */
    public FormEvent after(String... methodName){
        this.afterMethod.addAll(Arrays.asList(methodName));
        return this;
    }

    /**
     * 方法最后返回的对象js，不设置返回true
     */
    public FormEvent end(String returnJs){
        this.returnJs=returnJs;
        return this;
    }

    public String toString(){
        StringBuilder sb=new StringBuilder();
        int idx=this.methodName.indexOf("(");
        if(idx>=0){
            sb.append(this.methodName, 0, idx)
                .append(":function").append(this.methodName.substring(idx)).append("{");
        }else {
            sb.append(this.methodName).append(":function(){");
        }
        for(String bm : this.beforeMethod) sb.append("if(!this.").append(bm).append("()) return false;");
        if(EventMethod.JS==this.method){
            sb.append(this.methodJs);
            for(String mn : this.successMethod) sb.append("this.").append(mn).append("();");
            for(String mn : this.afterMethod) sb.append("this.").append(mn).append("();");
        }else if(EventMethod.AJAX==this.method){
            sb.append("this.requestData('").append(this.url).append("',").append(this.param)
                .append(",data=>{")
                .append("if(!data.code){this.setBack(true);if(data.msg)this.remind().success(data.msg);");
            for(String fd : this.fillData) sb.append("this.").append(fd).append("=").append("data.").append(fd).append(";");
            for(String mn : this.successMethod) sb.append("this.").append(mn).append("();");
            sb.append("}else{this.setBack(false);if(data.msg)this.remind().error(data.msg);}");
            for(String mn : this.afterMethod) sb.append("this.").append(mn).append("();");
            sb.append("});");
        }else if(EventMethod.MODAL==this.method||EventMethod.PAGE==this.method||EventMethod.DRAWER==this.method){
            sb.append("this.openPage('").append(this.url).append("',").append(this.param)
                .append(",(flag,data)=>{this.setBack(flag);")
                .append("if(flag){");
            for(String fd : this.fillData) sb.append("this['").append(fd).append("']=").append("data['").append(fd).append("'];");
            for(String mn : this.successMethod) sb.append("this.").append(mn).append("();");
            sb.append("}");
            for(String mn : this.afterMethod) sb.append("this.").append(mn).append("();");
            sb.append("},").append(this.width).append(",'").append(this.method).append("');");
        }
        sb.append(StringUtil.notSpace(returnJs)?("return "+returnJs):"return true;").append("},");
        return sb.toString();
    }
}
